#include "ql_oe.h"
#include "ql_gpio.h"
#include "../include/leds.hpp"
#include "defines.hpp"
#include "misc.h"

const Enum_PinLevel led::LED_ON  = PINLEVEL_HIGH;
const Enum_PinLevel led::LED_OFF = PINLEVEL_LOW;

const Enum_PinName led::DOG_IO   = PINNAME_GPIO4;
const Enum_PinName led::RELOAD_IO= PINNAME_GPIO2;
const Enum_PinName led::SOCKA_IO = PINNAME_GPIO1;
const Enum_PinName led::SOCKB_IO = PINNAME_GPIO3;
const Enum_PinName led::NET_IO   = PINNAME_GPIO5;
const Enum_PinName led::WORK_IO  = PINNAME_GPIO6;
led * led::ledDevice = nullptr;

void on_reload( Enum_PinName pin , int lev )
{
#if defined( __DEBUG__ )
    	std::cout << "reload pin lev changed." << std::endl;
#endif
	if( pin == led::RELOAD_IO && lev == PINLEVEL_LOW ){
		led::GetLed()->OnReload( true );
	}else{
		led::GetLed()->OnReload( false );
	}
}

led::led()
{
	// DOG_IO
    	Ql_GPIO_Init( DOG_IO , PINDIRECTION_OUT , PINLEVEL_LOW , PINPULLSEL_DISABLE );

	// RELOAD IO
	Ql_GPIO_Init( RELOAD_IO , PINDIRECTION_IN , PINLEVEL_LOW , PINPULLSEL_PULLUP );
	Ql_EINT_Enable( RELOAD_IO , EINT_SENSE_BOTH , on_reload );			//
	// WORK_IO
	Ql_GPIO_Init( WORK_IO , PINDIRECTION_OUT , PINLEVEL_LOW , PINPULLSEL_DISABLE );
	// SOCK A
	Ql_GPIO_Init( SOCKA_IO , PINDIRECTION_OUT , PINLEVEL_LOW , PINPULLSEL_DISABLE );
	// SOCK B
	Ql_GPIO_Init( SOCKB_IO , PINDIRECTION_OUT , PINLEVEL_LOW , PINPULLSEL_DISABLE );
	// NET
	Ql_GPIO_Init( NET_IO , PINDIRECTION_OUT , PINLEVEL_LOW , PINPULLSEL_DISABLE );
	Ql_GPIO_SetLevel( NET_IO   , (Enum_PinLevel)(LED_OFF ) );
	Ql_GPIO_SetLevel( WORK_IO  , (Enum_PinLevel)(LED_OFF ) );
	Ql_GPIO_SetLevel( SOCKA_IO , (Enum_PinLevel)(LED_OFF ) );
	Ql_GPIO_SetLevel( SOCKB_IO , (Enum_PinLevel)(LED_OFF ) );

	m_net_blink = false;
	m_reload_flag = false;

	init_dog_timer();
	init_net_led_timer();
	ledDevice = this;
}


led::~led()
{
	Ql_GPIO_SetLevel( NET_IO   , (Enum_PinLevel)(LED_OFF ) );
	Ql_GPIO_SetLevel( WORK_IO  , (Enum_PinLevel)(LED_OFF ) );
	Ql_GPIO_SetLevel( SOCKA_IO , (Enum_PinLevel)(LED_OFF ) );
	Ql_GPIO_SetLevel( SOCKB_IO , (Enum_PinLevel)(LED_OFF ) );
}

void led::socka( bool sw )
{
	int e = 0;
	#if defined( __DEBUG__ )
		std::cout << TYELLOW << "SOCK A LED=" << sw << std::endl;
	#endif
	if( sw )
		e = Ql_GPIO_SetLevel( SOCKA_IO , LED_ON );
	else
		e = Ql_GPIO_SetLevel( SOCKA_IO , LED_OFF );
	if( e ){

	}
}

void led::sockb( bool sw )
{
	int e = 0;
	#if defined( __DEBUG__ )
		std::cout << TYELLOW << "SOCK B LED=" << sw << std::endl;
	#endif
	if( sw )
		e = Ql_GPIO_SetLevel( SOCKB_IO , LED_ON );
	else
		e = Ql_GPIO_SetLevel( SOCKB_IO , LED_OFF );
	if( e ){

	}
}

void led::init_net_led_timer()
{
	m_net(1000);
	m_net.SetOwner([ this ]{
		m_net_blink = !(m_net_blink.load());
		if( m_net_blink == true ){
			m_net.Start( 2000 , true );
			Ql_GPIO_SetLevel( NET_IO , LED_ON );
			m_net_off.Start( -1 , true );
		}else{
			m_net.Start( 1000 , true );
			Ql_GPIO_SetLevel( NET_IO , LED_OFF );
			m_net_on.Stop();
			m_net_off.Stop();
		}
	});
    	m_net.Start( -1, true );

	m_net_off.SetOwner([ this ]{
		Ql_GPIO_SetLevel( NET_IO , LED_OFF );
		m_net_on.Start( -1 , true );
	});

	m_net_on.SetOwner([this]{
        	if(  m_net_blink == true )
            		Ql_GPIO_SetLevel( NET_IO , LED_ON );
        	m_net_off.Start( -1, true );
	});
}

void led::OnReload( bool type )
{
	if( type ){

		m_reload_timer1.SetOwner( [ this ]{
			m_reload_flag= true;				// 设置标志
		});
       	 	m_reload_timer1.Start( 3000 , true );

		m_reload_timer2.SetOwner([ this ]{
			m_reload_flag = false;				// 清除标识
		});
        	m_reload_timer2.Start( 15000 , true );
	}else{
		if( m_reload_flag == true ){
			__show_line_1( "%s%s%s" , TYELLOW  , "Reload pin is triggered" , TNORMAL );
			// 触发reload操作
			system("cp /data/etc/dtu/config.xml /data/sndtu/config.xml");
            		sync();
			abort();
		}else{
			m_reload_timer1.Stop();
			m_reload_timer2.Stop();
		}
	} 
}

void led::net( int type )
{
	if( type != 0 ){
		float c = 1000 / type;
		m_net_off( c  );
		m_net_on( c );
	}else{
		Ql_GPIO_SetLevel( NET_IO , (Enum_PinLevel)( LED_OFF ) );
	}
}

void led::init_dog_timer()
{
	m_wait_feed_timer.SetOwner([ this ]{
		Ql_GPIO_SetLevel( DOG_IO , LED_ON );
		m_feed_timer.Start( 200 , true );
	});

	m_feed_timer.SetOwner([ this ]{
		Ql_GPIO_SetLevel( DOG_IO , LED_OFF );
		m_wait_feed_timer.Start( 1000 , true );
	});

	m_wait_feed_timer.Start( 1000, true );
}

void led::work( bool sw )
{
	__show_line_1( "%s%s%d%s" , TYELLOW , " WORK LED=" , sw , TNORMAL );

	if( sw )
		Ql_GPIO_SetLevel( WORK_IO , LED_ON );
	else
		Ql_GPIO_SetLevel( WORK_IO , LED_OFF );
}
